package com.mengxj;

import com.common.collection.Classes;
import com.common.collection.Student;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 这里的以Final结尾的方法先不用管
 * @author mengxj
 */
public class StudentDemo {

    public static void main(String[] args) {
        StudentDemo demo = new StudentDemo();
        demo.addressAndInfo1(new Classes().students());
    }

    /**
     * 循环，逐个判断。
     * 循环可以选择迭代器，for循环，增强for循环，while等。这里只选择了增强for循环。
     * @param list 学生集合
     */
    private void filterByAge1(List<Student> list){
        for(Student student: list){
            if(student.getAge() < 15){
                System.out.println(student);
            }
        }
    }

    /**
     * 也是循环，类似filterByAge1。其实集合本身就有forEach方法，直接使用即可。
     * 其中student等价于filterByAge1循环中的student
     * @param list 学生集合
     */
    private void filterByAge2(List<Student> list){
        list.forEach(student -> {
            if(student.getAge() < 15){
                System.out.println(student);
            }
        });
    }

    /**
     * 这是我想要的最终方法，主要看这个。这个方法我当面和你们说。
     * @param list 学生集合
     */
    private void filterByAgeFinal(List<Student> list){
        list.stream().filter(student -> student.getAge() < 15).forEach(System.out :: println);
    }

    /**
     * 对名字去重最简单的方式，将名字存入集合中，每次判断新的名字在集合中是否存在即可。
     * 存在，不做处理；不存在，则放入名称集合，再输出。
     * @param list 学生集合
     */
    private void distinctName1(List<Student> list){
        List<String> names = new ArrayList<>();
        for(Student student: list){
            String name = student.getName();
            if(!names.contains(name)){
                names.add(name);
                System.out.println(name);
            }
        }
    }

    /**
     * 利用set集合的不重复性，将name直接放入set，自然就是去重结果了。之后遍历输出set集合即可
     * @param list 学生集合
     */
    private void distinctName2(List<Student> list){
        Set<String> names = new HashSet<>();
        for(Student student: list){
            String name = student.getName();
            names.add(name);
        }
        for(String name: names){
            System.out.println(name);
        }
    }

    /**
     * 在distinctName1稍作改动：循环中不判断，收集所有姓名。
     * 之后利用distinctName2思想，set的不重复性质，将名称去重
     * 之后遍历输出
     * @param list 学生集合
     */
    private void distinctName3(List<Student> list){
        List<String> names = new ArrayList<>();
        for(Student student: list){
            String name = student.getName();
            names.add(name);
        }
        Set<String> distinctName = new HashSet<>(names);
        for(String name: distinctName){
            System.out.println(name);
        }
    }

    /**
     * 这是我想要的最终方法，主要看这个。这个方法我当面和你们说。
     * @param list 学生集合
     */
    private void distinctNameFinal(List<Student> list){
        list.stream().map(Student::getName).distinct().forEach(System.out::println);
    }

    /**
     * 利用map，每次判断当前的名字在map中是否存在，不存在，
     * 则将名字和数字放入map，存在，则将名字对应的数字+1
     * 最后遍历map输出键值对即可
     * @param list 学生集合
     */
    private void nameTimes1(List<Student> list){
        Map<String, Integer> map = new HashMap<>();
        for(Student student: list){
            String name = student.getName();
            Integer time = map.get(name);
            if(Objects.isNull(time)){
                map.put(name, 1);
            }else{
                map.put(name, time + 1);
            }
        }
        for(Map.Entry<String, Integer> entry: map.entrySet()){
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }

    /**
     * 获取名称集合，再获取去重后名称集合
     * 遍历去重后的集合，再未去重的集合中找到存在的个数即可
     * @param list 学生集合
     */
    private void nameTimes2(List<Student> list){
        List<String> names = new ArrayList<>();
        for(Student student: list){
            String name = student.getName();
            names.add(name);
        }
        Set<String> distinctName = new HashSet<>(names);
        for(String name: distinctName){
            int count = 0;
            for(String na: names){
                if(na.equals(name)){
                    count ++;
                }
            }
            System.out.println(name + ":" + count);
        }
    }

    /**
     * 这是我想要的最终方法，主要看这个。这个方法我当面和你们说。
     * @param list 学生集合
     */
    private void nameTimesFinal(List<Student> list){
        list.stream().collect(Collectors.groupingBy(Student::getName)).forEach((k, v) -> System.out.println(k + ":" + v.size()));
    }

    /**
     * 一个个举例，年龄从1-100获取学生
     * @param list 学生集合
     */
    private void sortByAge1(List<Student> list){
        Map<Integer, Student> sortMap = new HashMap<>();
        for(Student student: list){
            sortMap.put(student.getAge(), student);
        }
        for(int i = 1; i < 100; i ++){
            Student student = sortMap.get(i);
            if(Objects.nonNull(student)){
                System.out.println(student);
            }
        }
    }

    /**
     * 冒泡排序
     * @param list 学生集合
     */
    private void sortByAge2(List<Student> list){
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size() - 1; j++) {
                Student sj = list.get(j), sj1 = list.get(j + 1);
                if(sj.getAge() > sj1.getAge()){
                    list.set(j + 1, sj);
                    list.set(j, sj1);
                }
            }
        }
        for(Student student: list){
            System.out.println(student);
        }
    }

    /**
     * 利用比较器接口
     * @param list 学生集合
     */
    private void sortByAge3(List<Student> list){
        Comparator<Student> comparator = (stu1, stu2) -> {
            Integer age1 = stu1.getAge(), age2 = stu2.getAge();
            return age1 - age2;
        };
        list.sort(comparator);
        list.forEach(System.out::println);
    }

    /**
     * 这是我想要的最终方法，主要看这个。这个方法我当面和你们说。
     * @param list 学生集合
     */
    private void sortByAgeFinal(List<Student> list){
        list.stream().sorted(Comparator.comparingInt(Student::getAge)).forEach(System.out::println);
    }

    /**
     * 用map来操纵篇，和之前统计times差不多
     * @param list 学生集合
     */
    private void addressAndInfo1(List<Student> list){
        Map<String, List<Student>> map = new HashMap<>();
        for(Student student: list){
            String address = student.getAddress();
            List<Student> students = map.get(address);
            if(Objects.isNull(students)){
                students = new ArrayList<>();
                map.put(address, students);
            }
            students.add(student);
        }
        for(Map.Entry<String, List<Student>> entry: map.entrySet()){
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }

    /**
     * 这是我想要的最终方法，主要看这个。这个方法我当面和你们说。
     * @param list 学生集合
     */
    private void addressAndInfoFinal(List<Student> list){
        list.stream().collect(Collectors.groupingBy(Student::getAddress)).forEach((k, v) -> System.out.println(k + ":" + v));
    }
}
